<?php

namespace app\model\system;

use app\model\BaseModel;

/**
 *
 */
class SysMenu extends BaseModel
{

    /**
     * The table associated with the model.
     *
     * @var string
     */
    protected $table = "sys_menu";


    const MENU = 1;
    const CATLOG = 2;
    const LINK = 3;
    const BUTTON = 4;
    public function children()
    {
        return $this->hasMany(SysMenu::class, 'parent_id', 'id');
    }

    public function parent()
    {
        return $this->belongsTo(SysMenu::class, 'parent_id', 'id');
    }

    private function getParams(): ?array
    {
        return $this->params ? $this->params : null;
    }

    private function getTypeTag(): string
    {
        return match ($this->type) {
            self::MENU => 'Menu',
            self::CATLOG => 'Catlog',
            self::LINK => 'Link',
            self::BUTTON => 'Button',
            default => 'Menu'
        };
    }
    private function getRouteName(): string
    {
        $trimedPath =  trim($this->routePath ?: '', '/');
        return $this->parent ? $this->parent->getRouteName()  . '.' . $trimedPath : $trimedPath;
    }

    private function getRoutePath(): ?string
    {
        return $this->routePath;
    }
    public function getRoutes(array &$menuIds)
    {
        // 过滤掉没有权限的菜单和按钮(type = 4)
        if (!in_array($this->id, $menuIds) || $this->type == 4) return null;
        $route = [
            'name' => $this->getRouteName(),
            'path' => $this->getRoutePath(),
            'component' => $this->component,
            'redirect' => $this->redirect,
            'meta' => [
                'title' => $this->name,
                'icon' => $this->icon,
                'hidden' => !$this->visible,
                'keepAlive' => $this->keepAlive,
                'alwaysShow' => $this->alwaysShow,
                'params' => $this->getParams(),
            ]
        ];
        $children = [];
        if (!$this->children->isEmpty()) {
            foreach ($this->children as $child) {
                if (!in_array($child->id, $menuIds) || $child->type == 4) continue;
                $children[] = $child->getRoutes($menuIds);
            }
            if ($children) $route['children'] = $children;
        }
        return $route;
    }

    public static function getTreeMenus(int $parentId, ?int $status = null, ?string $keywords = null): array
    {
        $menus = [];
        $nodes = SysMenu::where('parent_id', $parentId);
        if ($status !== null) $nodes->where('status', $status);
        if ($keywords) $nodes->where('name', 'like', "%{$keywords}%");
        $nodes = $nodes->order('sort', 'asc')->select();
        if (!$nodes->isEmpty()) {
            foreach ($nodes as $menu) {
                $route = [
                    "id" => $menu->id,
                    "parentId" => $menu->parent_id,
                    "name" => $menu->name,
                    "type" => $menu->type,
                    "routeName" => $menu->routeName,
                    "routePath" => $menu->routePath,
                    "component" => $menu->component,
                    "sort" => $menu->sort,
                    "visible" => $menu->visible,
                    "icon" => $menu->icon,
                    "redirect" => $menu->redirect,
                    "perm" => $menu->perm
                ];
                $children = $menu->getTreeMenus($menu->id);
                if ($children) $route['children'] = $children;
                $menus[] = $route;
            }
        }
        return $menus;
    }

    public static function getMenusOptions(int $parentId = 0): array
    {
        $menus = [];
        $nodes = SysMenu::where('parent_id', $parentId)->order('sort', 'asc')->select();
        if (!$nodes->isEmpty()) {
            foreach ($nodes as $menu) {
                $option = [
                    "value" => $menu->id,
                    "label" => $menu->name,
                    "tag" => $menu->getTypeTag(),
                ];
                $children = $menu->getMenusOptions($menu->id);
                if ($children) $option['children'] = $children;
                $menus[] = $option;
            }
        }
        return $menus;
    }

    public function getFormArray(): array
    {
        return [
            'id' => $this->id,
            'parentId' => $this->parent_id,
            'name' => $this->name,
            'type' => $this->type,
            'routeName' => $this->routeName,
            'routePath' => $this->routePath,
            'component' => $this->component,
            'sort' => $this->sort,
            'perm' => $this->perm,
            'visible' => $this->visible,
            'icon' => $this->icon,
            'redirect' => $this->redirect,
            'keepAlive' => $this->keepAlive,
            'alwaysShow' => $this->alwaysShow,
            'params' => $this->getParams(),
        ];
    }


    public function deleteNode(): bool
    {
        $children = $this->children;
        if (!$children->isEmpty()) {
            foreach ($children as $child) {
                $child->deleteNode();
            }
        }
        return $this->delete();
    }

    public function toArray(array $merges = []): array
    {
        $modeArray = $this->getFormArray();
        return $this->merge($modeArray, $merges);
    }
}
